package uz.rt.dicom.dictionary;

import uz.rt.dicom.ValueMultiplicity;
import uz.rt.dicom.ValueRepresentation;
import uz.rt.dicom.tag.DicomTag;

/**
 * A dictionary tag represents an entry in a dicom dictionary. The class extends a DicomTag to store the group and
 * element ids. Furthermore by implementing the IDictionaryItem interface the class will be have some standard
 * functions
 * to obtain dictionary item information.
 * <p/>
 * A dictionary tag contains the following properties:
 * <ul>
 * <li>All properties of a DicomTag</li>
 * <li>Name</li>
 * <li>Value representation (@see ValueRepresentation)</li>
 * <li>Value multiplicity (@see ValueMultiplicity) indicating the amount of data the tag can store</li>
 * <li>Status tag indicating if the tag is retired</li>
 * </ul>
 *
 * @author Tom Vercauteren
 * @version 0.0.1
 * @see DicomTag
 * @see IDictionaryItem
 */
public class DictionaryTag extends DicomTag implements IDictionaryItem<DicomTag, ValueRepresentation>
{
// ------------------------------ FIELDS ------------------------------

    /** Name of the dictionary tag */
    private final String name;
    /** Value representation indicating the datatype that is stored */
    private final ValueRepresentation vr;
    /** Value multiplicity stores the minimum and maximum amount of data stored inside the tag */
    private final ValueMultiplicity vm;
    /** Status tag indicating if the tag is retired */
    private final boolean isRetired;

// --------------------------- CONSTRUCTORS ---------------------------

    /**
     * Creates a dictionary tag with all its properties. The status tag isRetired is by default set to false.
     *
     * @param name    Name of the dictionary tag
     * @param group   16 bit unsigned binary group
     * @param element 16 bit unsigned binary element
     * @param vr      Value representation
     * @param vm      Value multiplicity
     * @throws Exception Thrown when trying to set an invalid value representation
     */
    public DictionaryTag(String name, int group, int element, String vr, String vm) throws Exception
    {
        super(group, element);
        this.name = name;
        this.vr = ValueRepresentation.getVr(vr.getBytes());
        this.vm = new ValueMultiplicity(vm);
        isRetired = false;
    }

    /**
     * Creates a dictionary tag with all its properties. The status tag isRetired is by default set to false.
     *
     * @param name      Name of the dictionary tag
     * @param group     16 bit unsigned binary group
     * @param element   16 bit unsigned binary element
     * @param vr        Value representation
     * @param vm        Value multiplicity
     * @param isRetired Status tag indicating if the tag is deprecated
     * @throws Exception Thrown when trying to set an invalid value representation
     */
    public DictionaryTag(String name, int group, int element, String vr, String vm, boolean isRetired) throws Exception
    {
        super(group, element);
        this.name = name;
        this.vr = ValueRepresentation.getVr(vr.getBytes());
        this.vm = new ValueMultiplicity(vm);
        this.isRetired = isRetired;
    }

// --------------------- GETTER / SETTER METHODS ---------------------

    public String getName()
    {
        return name;
    }

// ------------------------ CANONICAL METHODS ------------------------

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (!(o instanceof DictionaryTag)) return false;
        if (!super.equals(o)) return false;

        DictionaryTag that = (DictionaryTag) o;

        return isRetired == that.isRetired && !(name != null ? !name
                .equals(that.name) : that.name != null) && !(vm != null ? !vm
                .equals(that.vm) : that.vm != null) && !(vr != null ? !vr.equals(that.vr) : that.vr != null);
    }

    @Override
    public int hashCode()
    {
        int result = super.hashCode();
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (vr != null ? vr.hashCode() : 0);
        result = 31 * result + (vm != null ? vm.hashCode() : 0);
        result = 31 * result + (isRetired ? 1 : 0);
        return result;
    }

// ------------------------ INTERFACE METHODS ------------------------


// --------------------- Interface IDictionaryItem ---------------------

    public DicomTag getKey()
    {
        return new DicomTag(this.getGroup(), this.getElement());
    }

    public ValueRepresentation getType()
    {
        return vr;
    }

// -------------------------- OTHER METHODS --------------------------

    public ValueMultiplicity getVM()
    {
        return vm;
    }

    /**
     * Get the value representation of the dicom tag
     *
     * @return Value representation of the dicom tag
     */
    public ValueRepresentation getVR()
    {
        return vr;
    }
}
